

import java.beans.*;


import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;

import norsys.netica.*;
import norsys.neticaEx.NodeListEx;

import java.net.URI;

public class NoisyORBean {

  	
  public HashMap <String, Node> nodes;
  public HashMap <String, Node> nodes2;

  private NodeList nodeList;
  private NodeList parentListofNodeToConvert;
  private HashMap<Integer, HashMap<String, combination>> taggedCombinations; 
  private HashMap<String, Integer> parentIndices;
  
  public static Environ env;
  private Net net;
  private Net net2;
  private Net tempNet;
  private String date;
  private String logBuf = "";
  private String netName = "";
  private String netName2 = "";
  private String nodeNameToConvert = "";
  private boolean trueRNOR = true;
  private boolean replace5050with_Noisy_OR = false;
  
  // Link probabilities
  private HashMap<String, Float> linkProbs;
  private HashMap<String, Float> linkProbsTrue;
  
  // Print probabilities
  private HashMap<String, Float> printProbs;
  private HashMap<String, Float> printProbsTrue;
  private FileOutputStream log = null;
  private Writer writer = null;
  private Writer writerError = null;
  
    
  private float globalLeak;

  public NoisyORBean () {
    SimpleDateFormat sdf = new SimpleDateFormat( "MMM d, yyyy" );
    this.date = sdf.format( (new GregorianCalendar()).getTime() );
    nodes = new HashMap<String, Node>();
    nodes2 = new HashMap<String, Node>();
    
  }

  public String getDate () {
    return this.date;
  }

  public void resetForNewPatient(){
     
  }

  public void countParents(String filename)
  {
	  String path = "C:\\Users\\vanand\\VIBHA-DOCUMENTS\\Thesis Work\\LD Experiment";
	  path.replace("\\", "\\\\");
	    
  
	 try{
		 
		 env = new Environ ("+AnandV/IUPUI/120,310-4-A/6256"); 
		 net = loadNet(filename.substring(filename.lastIndexOf("\\")+1), nodes);
	     nodeList = net.getNodes();
	     logBuf = "CP_" + filename.substring(filename.lastIndexOf("\\")+1);
	     
	     if(log == null)
	      {
	    	  try {
				log  = new FileOutputStream(path + "\\" + logBuf+ "_log.txt");
				writer= new OutputStreamWriter(log);
				writerError = new OutputStreamWriter(new FileOutputStream(path + "\\" + logBuf + "ErrorLog.txt"));
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				
	      }	
	     writer.write("Parent counts - a proxy for edges in network for file: " + filename + "\n");
	     for(int k=0; k < nodeList.size(); k++)
	      {
	    	  
	    	 Node nn = nodeList.getNode(k);
	    	 String nnName;
	    	 int numParents = 0;
			try {
				nnName = nn.getName();
				numParents = nn.getParents().size();
				writer.write("\n" + nnName + "\t" + numParents);
			} catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	 
	    	
	      }
	     writer.flush();
	     writer.close();
      
	 } catch (Exception e) {
		  //-- We log any exceptions.
		  //-- Suggestion: during development, you may want to have your jsp page display the
		  //-- exception stack trace by calling getLog() below.
		  try {
			writer.write(e.toString());
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	  }
  }
  
  
 private Net loadNet(String name, HashMap <String, Node> nodes) throws Exception
 {
	 //String path = "C:\\Documents and Settings\\vanand\\My Documents\\Thesis Work\\ANOR";
	 String path = "C:\\Users\\vanand\\VIBHA-DOCUMENTS\\Thesis Work\\LD Experiment";
	 path.replace("\\", "\\\\");
    
    if(name != null)
    {
    
	    Net net = new Net (new Streamer (path + "\\" + name));
	
	    NodeList nodeList = net.getNodes();
		
		Iterator i = nodeList.iterator();
		while(i.hasNext())
		{
			Node n = (Node)i.next();
			nodes.put(n.getName(), n);
		}
		
		net.compile();
		return net;
    }
    else
    	return null;
 }

  private void initLinkProbs()
  {
	  linkProbs.put("eczema", new Float(0.048));
	  printProbs.put("eczema=True", new Float(0.048));
     
	  linkProbs.put("sex", new Float(0.022));
     	printProbs.put("sex=M", new Float(0.048));
     	
     	linkProbs.put("rsv_pos", new Float(0.4));
     	printProbs.put("rsv_pos=True", new Float(0.048));
     	
     	linkProbs.put("wz_er", new Float(0.37));
     	printProbs.put("wz_er=True", new Float(0.048));
     	
     	linkProbs.put("wheez", new Float(0.17));
     	printProbs.put("wheez=True", new Float(0.048));
     	
     	linkProbs.put("wz_hosp", new Float(0.104));
     	printProbs.put("wz_hosp=True", new Float(0.048));
     	
     	
     	linkProbs.put("xray", new Float(0.072));
     	printProbs.put("xray=True", new Float(0.048));
     	
     	linkProbs.put("drug", new Float(0.117));
     	printProbs.put("drug=True", new Float(0.048));
     	
     	//linkProbs.put("race", new Float(0.083));       // This was for Race = Other
     	linkProbs.put("race", new Float(0.02));       // This is for Race = Black, if considered as "True condition" and White as false condition
     	printProbs.put("race=Black", new Float(0.048));
     	
     	//linkProbs.put("ins_cat", new Float(0.07));	// This was for INS_CAT = Selfpay
      linkProbs.put("ins_cat", new Float(0.07));	// This was for INS_CAT = Private if consider as "True condition" and "Medicaid" as false condition
      printProbs.put("ins_cat=Private", new Float(0.048));
      
      linkProbs.put("global_leak", new Float(0.014));
      printProbs.put("global_leak=True", new Float(0.048));
      
  }

  private void initLinkProbsTrue()
  {
	  linkProbsTrue.put("eczema", new Float(0.048));
	  printProbsTrue.put("eczema=True", new Float(0.048));
     
	  linkProbsTrue.put("sex", new Float(0.022));
     	printProbsTrue.put("sex=M", new Float(0.048));
     	
     	linkProbsTrue.put("rsv_pos", new Float(0.4));
     	printProbsTrue.put("rsv_pos=True", new Float(0.048));
     	
     	linkProbsTrue.put("wz_er", new Float(0.37));
     	printProbsTrue.put("wz_er=True", new Float(0.048));
     	
     	linkProbsTrue.put("wheez", new Float(0.17));
     	printProbsTrue.put("wheez=True", new Float(0.048));
     	
     	linkProbsTrue.put("wz_hosp", new Float(0.104));
     	printProbsTrue.put("wz_hosp=True", new Float(0.048));
     	
     	
     	linkProbsTrue.put("xray", new Float(0.072));
     	printProbsTrue.put("xray=True", new Float(0.048));
     	
     	linkProbsTrue.put("drug", new Float(0.117));
     	printProbsTrue.put("drug=True", new Float(0.048));
     	
     	//linkProbs.put("race", new Float(0.083));       // This was for Race = Other
     	linkProbsTrue.put("race", new Float(0.02));       // This is for Race = Black, if considered as "True condition" and White as false condition
     	printProbsTrue.put("race=Black", new Float(0.048));
     	
     	//linkProbs.put("ins_cat", new Float(0.07));	// This was for INS_CAT = Selfpay
      linkProbsTrue.put("ins_cat", new Float(0.07));	// This was for INS_CAT = Private if consider as "True condition" and "Medicaid" as false condition
      printProbsTrue.put("ins_cat=Private", new Float(0.048));
      
      linkProbsTrue.put("global_leak", new Float(0.014));
      printProbsTrue.put("global_leak=True", new Float(0.048));
      
  }
  public String initSession (){
      resetForNewPatient();
	String returnMsg = null;
    try {
    	env = new Environ ("+AnandV/IUPUI/120,310-4-A/6256");
    //	loadNet(netName, nodes);
    //	loadNet(netName2, nodes2);
    	tempNet = new Net();
    	taggedCombinations = new HashMap<Integer, HashMap<String, combination>>();
    	parentIndices = new HashMap<String, Integer>();
    	linkProbs = new HashMap<String, Float> ();
    	linkProbsTrue = new HashMap<String, Float> ();
    	printProbs = new HashMap<String, Float> ();
    	printProbsTrue = new HashMap<String, Float> ();
    	initLinkProbs();
    	initLinkProbsTrue();
    	 
       	
    	
    	
    }
    catch (Exception e) {
	returnMsg = e.getMessage();
	e.printStackTrace();
    }
    return returnMsg;
  }

  public void processRequest (String filename_org, String filename_other,
  								String nodeName, String tRNOR, String replace5050withNOR)
  {
	  String path = "C:\\Documents and Settings\\vanand\\My Documents\\Thesis Work\\ANOR";
	  path.replace("\\", "\\\\");
     
      //-- Do HTTP stuff
	  String yesno = tRNOR;
	     
	  if(yesno.contains("no"))
      {
    	  trueRNOR = false;
      }
      else
      {
    	  trueRNOR = true;
      }
	  
	  yesno = replace5050withNOR;
	  if(yesno.contains("no"))
      {
		  replace5050with_Noisy_OR = false;
      }
      else
      {
    	  replace5050with_Noisy_OR = true;
      }
	  
      logBuf = ""; //resets log
      if(trueRNOR)
    	  logBuf = "trueRNOR";
      else
    	  logBuf = "falseRNOR";
      
      if(replace5050with_Noisy_OR)
    	  logBuf += "_replace5050wNOR_";
    
       if(log == null)
      {
    	  try {
			log  = new FileOutputStream(path + "\\" + logBuf+ "_log.txt");
			writer= new OutputStreamWriter(log);
			writerError = new OutputStreamWriter(new FileOutputStream(path + "\\" + logBuf + "ErrorLog.txt"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			
		  
		    
      }

      netName = filename_org;
      netName2 = filename_other;
      nodeNameToConvert = nodeName;
      
      if(taggedCombinations != null)
    	  taggedCombinations.clear();

            //-- Do Netica stuff
      try {
	  if (env == null) {
	      env = Environ.getDefaultEnviron();
	      if (env == null) {
		  String errMsg = initSession();
		  if (env == null) {
		      log( errMsg );
		      return; //no point in continuing
		  }
	      }
	  }

	 // if ( net == null)        // Reload every time
	 {
	      log( "Reloaded ..." );
	      net = loadNet(netName, nodes);
	      nodeList = net.getNodes();
	      net2 = loadNet(netName2, nodes2);
	  }

	  net.retractFindings();
	  net.compile();
	  net2.compile();
	  
	  float[] probs_org = null;
	  float[] probs_other = null;
	  
	  Node n_org = nodes.get(nodeNameToConvert)	;
	  Node n_other = nodes2.get(nodeNameToConvert)	;
	  parentListofNodeToConvert = n_org.getParents();
	  
	  probs_org = n_org.getCPTable (null);
	  probs_other = n_other.getCPTable (null);
	  
	  
	  boolean changed = false;
	  
	  
	  float[][] allProbs = null;
	  allProbs = getNodeAllProbs(n_org,null);
	  
	  for(int i = 0; i < parentListofNodeToConvert.size(); i++)
	  {
		  Node n = parentListofNodeToConvert.getNode(i);
		  parentIndices.put(n.getName(), i);
	  }
	  
	  nodeList.remove((Node)n_org);
	  linkProbs.clear();
	  linkProbsTrue.clear();
	  initLinkProbs();
	  initLinkProbsTrue();
	  
	  for (int iList = 1; iList <= nodeList.size(); iList++ )
	  {
		  HashMap<String, combination> map = new HashMap<String, combination> ();
		  getAllCombinations(iList, map, n_org);
		  taggedCombinations.put(iList, map);
		  
	  }
	  
	 writer.flush();
	 writer.close();
	 writerError.flush();
	 writerError.close();
	 
	   changed = true;
      
      
           
	  
      /*
      int i = 0;
      
      while (i < probs_org.length )
	  {
		  if(probs_org[i] == 0.5){
			  // replace with other
			  probs_org[i] = probs_other[i];
			  changed = true;
		  }
		  i++;
	  }
	  */
      if(changed)
	  	{
	  	//	n_org.setCPTable(probs_org);
    	 
    	    String fn = path + "\\" + logBuf + "Net.dne";
    	  	Streamer os = new Streamer(fn);
	  		net.write(os);
	  	}
	 	
     // Iterator   i = printProbs.entrySet().iterator();
      
     // writer.write("***********************************************************************************");
     // writer.write("\n");
     // while(i.hasNext())
     // {
     //	  writer.write(i.next().toString());
    //	  writer.write("\n");
    	   
    //  }
    	  
      
      } catch (Exception e) {
	  //-- We log any exceptions.
	  //-- Suggestion: during development, you may want to have your jsp page display the
	  //-- exception stack trace by calling getLog() below.
	  try {
		writer.write(e.toString());
	} catch (IOException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}
      }

  }

    public String getLog() { return logBuf; }

    public void log( String msg ){
    }
    
    public Node getNode(String name) {
    	 return(nodes.get(name));
    	
    }
    
    public static float[][] getNodeAllProbs (Node node, float[][] probs) throws NeticaException {
        NodeList parents = node.getParents();
        int numStates  = node.getNumStates();
        if (probs == null) {
  	  probs = new float[(int) NodeListEx.sizeCartesianProduct (node.getParents())][numStates];
        }
        int[] parentStates = new int[parents.size()];  //initially all zero
        int probSet = 0;
        while (true){
            float[] vecp = node.getCPTable (parentStates, null);
            if (vecp == null)  break;
            for (int st = 0;  st < numStates;  ++st)  probs[probSet][st] = vecp[st];
            if (NodeListEx.nextStates (parentStates, parents)) 
                break;
            ++probSet;
        }
        return probs;
    }
    
    public void getAllCombinations(int r, HashMap<String, combination> map, Node nodeForRNOR)
    {
	    int[] indices;
	    combinationGenerator x = new combinationGenerator (nodeList.size(), r);
	    float[] cptRow = {0.0f, 0.0f};
	    int[]   pStates = new int[parentListofNodeToConvert.size()];
	    
	    
	    while (x.hasMore ()) 
	    {
	      combination c = new combination();
	      indices = x.getNext ();
	      
			try {
				 NodeList nList = new NodeList(tempNet);
				  
				 
				  for (int i = 0; i < indices.length; i++) 
			      {
					 Object n =nodeList.get(indices[i]);
			    	 nList.add(i,n);
			    	 
			      }
			      
				 
			      
			      Node nn = null;
			      String nnName = "";
			      int index = 0;
			      boolean loop = true;
			      int race_k = getParentIndex("race");
			      int ins_cat_k = getParentIndex("ins_cat");
			      
			      //  while(loop)
			        {
				/*	      for(int k=0; k < parentListofNodeToConvert.size(); k++)
					      {
					    	// Set everything to default state of (FALSE)  
					    	 nn = parentListofNodeToConvert.getNode(k);
					    	 nnName = nn.getName();
					    	 index = 0;
					    	 
					    	 if(nnName.compareTo("race")== 0)
					    	 {
					    		 race_k = k;
					    		 index = nn.state("White").getIndex();		// False condition
					    	 }
					    	 else if (nnName.compareTo("ins_cat")==0)
					    	 {
					    		 ins_cat_k = k;
					    		 index = nn.state("Medicaid").getIndex();	// False condition
					    	 }
					    	 else if (nnName.compareTo("sex")==0)
					    	 {
					    		 index = nn.state("F").getIndex();			// False condition
					    	 }
					    	 else
					    	 {
					    		 index = nn.state("False").getIndex();
					    	 }
					    	 pStates[parentIndices.get(parentListofNodeToConvert.getNode(k).getName())] = index;	
					      }
				*/
			        	  pStates = resetParentStates();
			        	  
					      //Reset again
					      nn = null;
					      nnName = "";
					      index = 0;
					      boolean ins_cat_false = false;           // to dichotomize the ins_cat and race nodes
					      boolean race_false = false;
					      
					      for(int j = 0; j < nList.size(); j++)
					      {
					    	 nn = nList.getNode(j);
					    	 nnName = nn.getName();
					    	 index = 0;
					    	 
					    	 if(nnName.compareTo("race")== 0)
					    	 {
					    		 index = nn.state("Black").getIndex();
					    		 race_false = true;
					    	 }
					    	 else if (nnName.compareTo("ins_cat")==0)
					    	 {
					    		 index = nn.state("Private").getIndex();
					    		 ins_cat_false = true;
					    	 }
					    	 else if (nnName.compareTo("sex")==0)
					    	 {
					    		 index = nn.state("M").getIndex();
					    	 }
					    	 else
					    	 {
					    		 index = nn.state("True").getIndex();
					    	 }
					    	 pStates[parentIndices.get(nList.getNode(j).getName())] = index;
					      }
					    /*  
					      Float f = calculateRNOR(nList, pStates, nodeForRNOR);
					      c.set(nList.toString(),f);
					      map.put(nList.toString(), c);
					      if(f <= 1.0f && !(f < 0.0f) )
					      {
					    	  cptRow[0]= f;
					    	  cptRow[1] = 1-f;
					      
					      	  setCPTableforRow(nodeForRNOR,pStates,cptRow);
					      }
					      else
					      {
					    	  log.error("CPT calculated is negative for: " + nList.toString());
					      }
					      */
					      float [] retRow = doStuff(nList, pStates, nodeForRNOR);
					      
					      	  if(!ins_cat_false)  // We should set all the false states as well for this combination- ie. Selfpay and Unknown besides Medicaid
						      {
						    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Medicaid").getIndex();
						    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    	  
						    	  if(!race_false)
							      {
						    		  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("White").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Hispanic").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Other").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);	  
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Unknown").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							      }
						    	  
						    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Selfpay").getIndex();
						    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    	  if(!race_false)
							      {
						    		  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("White").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Hispanic").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Other").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);	  
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Unknown").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							      }
						    	  
						    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("unknown").getIndex();
						    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    	  if(!race_false)
							      {
						    		  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("White").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Hispanic").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Other").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);	  
							    	  
							    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Unknown").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	  
							      }
						    	  					    		  
						      }
					      
					      
					      	  if(!race_false)
						      {
						    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("White").getIndex();
						    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    	  if(!ins_cat_false)  // We should set all the false states as well for this combination- ie. Selfpay and Unknown besides Medicaid
							      {
						    		  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Medicaid").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    		  
							    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Selfpay").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	
							    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("unknown").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							      }
						    	  
						    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Hispanic").getIndex();
						    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    	  if(!ins_cat_false)  // We should set all the false states as well for this combination- ie. Selfpay and Unknown besides Medicaid
							      {
						    		  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Medicaid").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    		  
						    		  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Selfpay").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	
							    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("unknown").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							      }
						    	  
						    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Other").getIndex();
						    	  setCPTableforRow(nodeForRNOR, pStates, retRow);	  
						    	  if(!ins_cat_false)  // We should set all the false states as well for this combination- ie. Selfpay and Unknown besides Medicaid
							      {
						    		  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Medicaid").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    		  
						    		  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Selfpay").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	
							    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("unknown").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							      }
						    	  
						    	  pStates[parentIndices.get("race")] = parentListofNodeToConvert.getNode(race_k).state("Unknown").getIndex();
						    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    	  if(!ins_cat_false)  // We should set all the false states as well for this combination- ie. Selfpay and Unknown besides Medicaid
							      {
						    		  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Medicaid").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
						    		  
						    		  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("Selfpay").getIndex();
						    		  setCPTableforRow(nodeForRNOR, pStates, retRow);
							    	
							    	  pStates[parentIndices.get("ins_cat")] = parentListofNodeToConvert.getNode(ins_cat_k).state("unknown").getIndex();
							    	  setCPTableforRow(nodeForRNOR, pStates, retRow);
							      }
						      }
			        	
					       
					}
			} catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	     
	    }
	    
    }
    
    private float[] doStuff(NodeList nList, int[] pStates, Node nodeForRNOR)
    {
    	Float f_true  = 0.0f;
    	//Run this only in TrueRNOR mode, as the the other Noisy OR approach writes to CPT regardless so
    	// successive calculations are wron.
    	if(trueRNOR)
    	{
    		f_true = calculateRNORTrue(nList, pStates, nodeForRNOR);
    	}
    	Float f = calculateRNOR(nList, pStates, nodeForRNOR);
    	
    	
    	float [] cptRow = {0.5f, 0.5f};
    	
    	try {
			writer.write(getParentStateName(pStates)+ ": " + f_true + "," + f);
			writer.write("\n");
			writer.flush();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(trueRNOR)
		{
			if(f_true <= 1.0f && !(f_true < 0.0f) )
		    {
		    	  cptRow[0]= f_true;
		    	  cptRow[1] = 1-f_true;
		      
		      	  setCPTableforRow(nodeForRNOR,pStates,cptRow);
		    }
		    else if(replace5050with_Noisy_OR)
		    {
		    	if(f <= 1.0f && !(f < 0.0f) )    // Use the falseRNOR score - it should be better than 50-50 but replace only if 50-50 in original CPT
			    {								 // taken care of in setCPTRow()
			    	  cptRow[0]= f;
			    	  cptRow[1] = 1-f;
			      
			      	  setCPTableforRow(nodeForRNOR,pStates,cptRow);
			    }
		    }
		    return  cptRow;
		}
		else
		{
		   if(f <= 1.0f && !(f < 0.0f) )
		    {
		    	  cptRow[0]= f;
		    	  cptRow[1] = 1-f;
		      
		      	  setCPTableforRow(nodeForRNOR,pStates,cptRow);
		    }
		    else
		    {
		    	  //log.error("CPT calculated is negative for: " + nList.toString());
		    }
		    return  cptRow;
		}
    }
    
    
    private void setCPTableforRow(Node n, int[] pStates, float[] cptRow)
    {
    	 float [] vecp = {0.0f, 0.0f}; 
         
   
    	 String s = "";
		  
	    	s += getParentStateName(pStates);
		  
		  
		  
    	 try {
    		 // Always set for Noisy-OR approach
    		 if(trueRNOR == false)
    		 {
    			 n.setCPTable(pStates,cptRow);
    			 return;
    			   		 
    		 }
    		
    		 if(trueRNOR == true)
    		 {
    			// if true RNOR then only look for exisiting values of CPT and replace if doesn't exist
				vecp = n.getCPTable(pStates, null);
			  // Does the value exist for this parent states in CPT table
			      if (vecp != null)
			      {
			    	  if (vecp[0]== 0.5) // 50-50 chance then we set it to calculated value
			    	  {
			    		  n.setCPTable(pStates,cptRow);
			   // 		  writer.write("Setting CPT for row - " + s + " = " + Float.valueOf(cptRow[0]));
			   // 		   writer.write("\n");
			    		  if(cptRow[0] == 0.5)
			    		  {
			    			  try {
			    				  
								writerError.write("No valid RNOR score can be calculated for " + getParentStateName(pStates));
								writerError.write("\n");
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
			    		  }
			    		  	    		  
			    	  }
			    	  else
			    	  {
			  //  		  writer.write("USED ORIGINAL SCORE!" + s + " = " + Float.valueOf(vecp[0]));
			  //  		   writer.write("\n");
			    		 
			    		   
			    	  }
			    	  
			      }
    		 }
		  } 
	      catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
		  }
	      
    }
    
    
    private float[] getCPTableforRow(Node n, int[] pStates)
    {
    	float[] cptRow = {0.f, 0.0f}; 
    	try {
			cptRow = n.getCPTable(pStates, null);
		  } 
	      catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
		  }
	      return cptRow;
    }
    
    private int[] resetParentStates()
    {
    	int[]   pStates = new int[parentListofNodeToConvert.size()];
    	try {  
	    	for(int k=0; k < parentListofNodeToConvert.size(); k++)
		      {
		    	// Set everything to default state of (FALSE)  
		    	 Node nn = parentListofNodeToConvert.getNode(k);
		    	 String nnName = nn.getName();
		    	 int index = 0;
		    	 
		    	 if(nnName.compareTo("race")== 0)
		    	 {
		    		 index = nn.state("White").getIndex();		// False condition
		    	 }
		    	 else if (nnName.compareTo("ins_cat")==0)
		    	 {
		    		 index = nn.state("Medicaid").getIndex();	// False condition
		    	 }
		    	 else if (nnName.compareTo("sex")==0)
		    	 {
		    		 index = nn.state("F").getIndex();			// False condition
		    	 }
		    	 else
		    	 {
		    		 index = nn.state("False").getIndex();
		    	 }
		    	 pStates[parentIndices.get(parentListofNodeToConvert.getNode(k).getName())] = index;	
		      }
    	 }
    	catch (NeticaException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	  return pStates;
    }
    
    private int getParentIndex(String name)
    {
    	
    	  for(int k=0; k < parentListofNodeToConvert.size(); k++)
	      {
	    	// Set everything to default state of (FALSE)  
	    	 Node nn = parentListofNodeToConvert.getNode(k);
	    	 String nnName;
			try {
				nnName = nn.getName();
				 if(nnName.compareTo(name)== 0)
		    	 {
		    		return k;
		    	 }
			} catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	 
	    	
	      }
    	  return -1;
    }
    
    private String getParentStateName(int[] pStates)
    {
    	String nnName = "";
    	  for(int k=0; k < parentListofNodeToConvert.size(); k++)
	      {
	    	 Node nn = parentListofNodeToConvert.getNode(k);
	    	 
			try {
				String s = nn.getName();
				nnName += s + "=" + nn.state(pStates[k]) + ",";
				
				 
			} catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return "";
			}
	    	 
	      }
    	  return nnName;
    	  
    }
    
    public Float calculateRNOR(NodeList nList, int[] pStates, Node nodeForRNOR)
    {
    	Float retVal = 0.0f;
    	Node n1, n2;
    	Float f1,f2,probScore;
    	NodeList subtractList, numeratorList, denominatorList;
    	
    	float[] cptRow = {0.0f, 0.0f};
    	
    	try { 	
    		if(nList.size() == 1)
    		{
    			n1 = (Node) nList.get(0);
    			retVal = linkProbs.get(n1.getName());
    			    		
    			linkProbs.put(nList.toString(), retVal);    // also save it for further calculations
    			printProbs.put(getParentStateName(pStates), retVal);
    		}
    		else if(nList.size() == 2)
	    	{
	    		 n1 = (Node) nList.get(0);
	    		 n2 = (Node) nList.get(1);
	    		 f1 = linkProbs.get(n1.getName());
	    		 f2 = linkProbs.get(n2.getName());
	    		 
	    		retVal = 1 - ( (1 - f1)* (1 - f2)) ; 
	    		
	    		linkProbs.put(nList.toString(), retVal);    // also save it for further calculations
	    		printProbs.put(getParentStateName(pStates), retVal);
	    	}
    	   	else
	    	{
	    		subtractList = new NodeList(tempNet);
	    		Node nodeToSubtract, nodeToSubtractPlusOne;
	    		ArrayList<Float> resultProbs = new ArrayList<Float>();
	    		ArrayList<Float> resultProbsTrue = new ArrayList<Float>();
	    		
	    		for(int i=0; i< nList.size(); i++)
	    		{
	    			nodeToSubtract = nList.getNode(i);
	    			subtractList.clear();
	    			// Numerator
	    			numeratorList = new NodeList(nList);
	    			subtractList.add((Node) nodeToSubtract);
	    			setSubtract(numeratorList, subtractList);  //After the call numeratorSet = nList - subtractList
	    			
	    			
	    			// Denominator
	    			subtractList.clear();
	    			denominatorList = new NodeList(nList);
	    			subtractList.add((Node) nodeToSubtract);
	    			if((nList.size() - i) == 1)  // Are we at the end of the list, then the plus one subtract node needs to be wrapped
	    			{
	    				nodeToSubtractPlusOne = nList.getNode(0);
	    			}
	    			else
	    			{
	    				nodeToSubtractPlusOne = nList.getNode(i+1);
	    			}
	    			subtractList.add((Node) nodeToSubtractPlusOne);
	    			setSubtract(denominatorList, subtractList);  //After the call denominatorSet = nList - subtractList
	    			
	    			
	    			probScore = calculateProbScore(numeratorList, denominatorList, pStates, nodeForRNOR);
	    			resultProbs.add(probScore);
	    			    			
	    		}
	    		
	    		// Now mulitply indivdual scores and subtract from 1
	    		retVal = resultProbs.get(0);
	    		for(int i=1; i < resultProbs.size(); i++)
	    		{
	    			retVal = retVal*resultProbs.get(i);
	    		}
	    		retVal = 1 - retVal;
	    		
	    		if(retVal == 0)
	    		{
	    			retVal = 0.0f; 
	    		}
	    		else if(retVal == 1)
	    		{
	    			retVal = 1.0f;
	    		}
	    		
	    		
	    		if(!linkProbs.containsKey(nList.toString()))
				{
					linkProbs.put(nList.toString(), retVal);    // also save it for further calculations
					printProbs.put(getParentStateName(pStates), retVal);
				}
	    		
	    	/*
	    		if(rVal >= 0.0f && rVal <= 1.0f)
	    		{
	    			//linkProbs.put(nList.toString(), retVal);    // also save it for further calculations
	    		}
	    		else
	    		{
	    			try {
						writer.write("Combination -VE for:" + getParentStateName(pStates));
						writer.write("\n");
						writer.write("CPT calculated is negative for: " + nList.toString()+ " = " +  rVal.toString());
						writer.write("\n");
						for(int i=0; i < resultProbsTrue.size(); i++)
			    		{
			    			writer.write("val_" + i + ": "  + resultProbsTrue.get(i));
			    			writer.write("\n");
			    			   
			    		}
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
	    			
	    		}
	    	*/	
	    	}
	    	
    	} catch (NeticaException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return retVal;
    }
    
    public Float calculateRNORTrue(NodeList nList, int[] pStates, Node nodeForRNOR)
    {
    	Float retValTrue = 0.0f;
    	Node n1, n2;
    	Float f1,f2,probScoreTrue;
    	NodeList subtractList, numeratorList, denominatorList;
    	
    	float[] cptRow = {0.0f, 0.0f};
    	float [] vecp = {0.0f, 0.0f}; 
    	
    	try { 	
    		if(nList.size() == 1)
    		{
    			n1 = (Node) nList.get(0);
    			vecp = nodeForRNOR.getCPTable(pStates, null);
    			if(vecp[0] == 0.5)
    			{
    				retValTrue = linkProbsTrue.get(n1.getName());
    			}
    			else
    			{
    				retValTrue = vecp[0];
    			}
    			linkProbsTrue.put(nList.toString(), retValTrue);    // also save it for further calculations
    			printProbsTrue.put(getParentStateName(pStates), retValTrue);
    		}
    		else if(nList.size() == 2)
	    	{
	    		 n1 = (Node) nList.get(0);
	    		 n2 = (Node) nList.get(1);
	    		 f1 = linkProbsTrue.get(n1.getName());
	    		 f2 = linkProbsTrue.get(n2.getName());
	    		 
	    		 vecp = nodeForRNOR.getCPTable(pStates, null);
	    		 if(vecp[0] == 0.5)
	    		 {
	    			retValTrue = retValTrue = 1 - ( (1 - f1)* (1 - f2)) ; 
	    		 }
	    		 else
	    		 {
	    			retValTrue = vecp[0];
	    		 } 
	    		 
	    		
	    		linkProbsTrue.put(nList.toString(), retValTrue);    // also save it for further calculations
	    		printProbsTrue.put(getParentStateName(pStates), retValTrue);
	    	}
    	   	else
	    	{
	    		subtractList = new NodeList(tempNet);
	    		Node nodeToSubtract, nodeToSubtractPlusOne;
	    		ArrayList<Float> resultProbs = new ArrayList<Float>();
	    		ArrayList<Float> resultProbsTrue = new ArrayList<Float>();
	    		
	    		for(int i=0; i< nList.size(); i++)
	    		{
	    			nodeToSubtract = nList.getNode(i);
	    			subtractList.clear();
	    			// Numerator
	    			numeratorList = new NodeList(nList);
	    			subtractList.add((Node) nodeToSubtract);
	    			setSubtract(numeratorList, subtractList);  //After the call numeratorSet = nList - subtractList
	    			
	    			
	    			// Denominator
	    			subtractList.clear();
	    			denominatorList = new NodeList(nList);
	    			subtractList.add((Node) nodeToSubtract);
	    			if((nList.size() - i) == 1)  // Are we at the end of the list, then the plus one subtract node needs to be wrapped
	    			{
	    				nodeToSubtractPlusOne = nList.getNode(0);
	    			}
	    			else
	    			{
	    				nodeToSubtractPlusOne = nList.getNode(i+1);
	    			}
	    			subtractList.add((Node) nodeToSubtractPlusOne);
	    			setSubtract(denominatorList, subtractList);  //After the call denominatorSet = nList - subtractList
	    			
	    			
	    			probScoreTrue = calculateTrueProbScore(numeratorList, denominatorList, pStates, nodeForRNOR);
	    			resultProbsTrue.add(probScoreTrue);
	    			
	    			    			
	    		}
	    		
	    				
	    		
	    		// Now mulitply indivdual scores and subtract from 1
	    		retValTrue = resultProbsTrue.get(0);
	    		for(int i=1; i < resultProbsTrue.size(); i++)
	    		{
	    			retValTrue = retValTrue*resultProbsTrue.get(i);
	    		}
	    		retValTrue = 1 - retValTrue;
	    		
	    		if(retValTrue == 0)
	    		{
	    			retValTrue = 0.0f; 
	    		}
	    		else if(retValTrue == 1)
	    		{
	    			retValTrue = 1.0f;
	    		}
	    		
	    		//if(retValTrue >= 0.0f && retValTrue <= 1.0f)	    		
	    		{
		    		if(!linkProbsTrue.containsKey(nList.toString()))   // we store it for future calculations if needed
					{
						linkProbsTrue.put(nList.toString(), retValTrue);    // also save it for further calculations
						printProbsTrue.put(getParentStateName(pStates), retValTrue);
					}
	    		}
	    		//else
	    		if(retValTrue < 0.0f || retValTrue > 1.0f)	   
	    		{
	    			try {
						writerError.write("Combination -VE or +VE for:" + getParentStateName(pStates) + ":" + retValTrue.toString());
						writerError.write("\n");
						//writerError.write("CPT calculated is negative for: " + nList.toString()+ " = " +  retValTrue.toString());
						//writerError.write("\n");
						for(int i=0; i < resultProbsTrue.size(); i++)
			    		{
			    			writerError.write("val_" + i + ": "  + resultProbsTrue.get(i));
			    			writerError.write("\n");
			    			   
			    		}
					} catch (IOException e) {
						// TODO Auto-generated catch block
						try {
							writer.write(e.toString());
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
						e.printStackTrace();
					}
	    			
	    		}
	    	}
	    	
    	} catch (NeticaException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return retValTrue;
    }
    
    
    public void setSubtract(NodeList initialSet, NodeList setToSubtract)  // returns the initialSet as modified set
    {
  		for(int i=0; i< setToSubtract.size(); i++)
		{
  			Node n = setToSubtract.getNode(i);
  			
  			int index = initialSet.indexOf((Node)n);
  			initialSet.remove(index);
		}
    		
    }
    
    public float[] getOriginalCPTValue(NodeList nList, Node nodeForOrgValue)
    {
    	int[]   pStates = new int[parentListofNodeToConvert.size()];
    	float[] cptRow = {0.0f,0.0f};
    	try {
    		
    		
    		
    		Node nn = null;
		      String nnName = "";
		      int index = 0;
		      
    		for(int k=0; k < parentListofNodeToConvert.size(); k++)
		      {
		    	// Set everything to default state of (FALSE)  
		    	 nn = parentListofNodeToConvert.getNode(k);
		    	 nnName = nn.getName();
		    	 index = 0;
		    	 
		    	 if(nnName.compareTo("race")== 0)
		    	 {
		    		
		    		 index = nn.state("White").getIndex();		// False condition
		    	 }
		    	 else if (nnName.compareTo("ins_cat")==0)
		    	 {
		    		 
		    		 index = nn.state("Medicaid").getIndex();	// False condition
		    	 }
		    	 else if (nnName.compareTo("sex")==0)
		    	 {
		    		 index = nn.state("F").getIndex();			// False condition
		    	 }
		    	 else
		    	 {
		    		 index = nn.state("False").getIndex();
		    	 }
		    	 pStates[parentIndices.get(parentListofNodeToConvert.getNode(k).getName())] = index;	
		      }
		      
		      //Reset again
		      nn = null;
		      nnName = "";
		      index = 0;
		      
		      for(int j = 0; j < nList.size(); j++)
		      {
		    	 nn = nList.getNode(j);
		    	 nnName = nn.getName();
		    	 index = 0;
		    	 
		    	 if(nnName.compareTo("race")== 0)
		    	 {
		    		 index = nn.state("Black").getIndex();
		    		 
		    	 }
		    	 else if (nnName.compareTo("ins_cat")==0)
		    	 {
		    		 index = nn.state("Private").getIndex();
		    		 
		    	 }
		    	 else if (nnName.compareTo("sex")==0)
		    	 {
		    		 index = nn.state("M").getIndex();
		    	 }
		    	 else
		    	 {
		    		 index = nn.state("True").getIndex();
		    	 }
		    	 pStates[parentIndices.get(nList.getNode(j).getName())] = index;
		      }
		      cptRow = nodeForOrgValue.getCPTable(pStates,null);
    		
    		
    		
    	} catch (ArrayIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NeticaException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return cptRow;
    }
    
    public float[] getCPTValueforNodeStates(NodeList nList, Node nodeForOrgValue, int [] desiredStates)
    {
    	int[]   pStates = new int[parentListofNodeToConvert.size()];
    	
    	float[] cptRow = {0.0f,0.0f};
    	try {
    	    		
    		  Node nn = null;
		      String nnName = "";
		      int index = 0;
		      
		      for(int k=0; k < parentListofNodeToConvert.size(); k++)
		      {
		    	// Set everything to default state of (FALSE)  
		    	 nn = parentListofNodeToConvert.getNode(k);
		    	 nnName = nn.getName();
		    	 index = 0;
		    	 
		    	 if(nnName.compareTo("race")== 0)
		    	 {
		    		
		    		 index = nn.state("White").getIndex();		// False condition
		    	 }
		    	 else if (nnName.compareTo("ins_cat")==0)
		    	 {
		    		 
		    		 index = nn.state("Medicaid").getIndex();	// False condition
		    	 }
		    	 else if (nnName.compareTo("sex")==0)
		    	 {
		    		 index = nn.state("F").getIndex();			// False condition
		    	 }
		    	 else
		    	 {
		    		 index = nn.state("False").getIndex();
		    	 }
		    	 pStates[parentIndices.get(parentListofNodeToConvert.getNode(k).getName())] = index;	
		      }
		      
		      //Reset again
		      nn = null;
		      nnName = "";
		      index = 0;
		
		      for(int j = 0; j < nList.size(); j++)
		      {
		    	 nn = nList.getNode(j);
		    	 nnName = nn.getName();
		    	 index = 0;
		    	 
		    	 if(nnName.compareTo("race")== 0)
		    	 {
		    		 index = desiredStates[parentIndices.get(nList.getNode(j).getName())];   // get the desired state for the node e.g. race = Hispanic
		    		 
		    	 }
		    	 else if (nnName.compareTo("ins_cat")==0)
		    	 {
		    		 index = desiredStates[parentIndices.get(nList.getNode(j).getName())];   // get the desired state for the node e.g. race = Hispanic
		    	 }
		    	 else if (nnName.compareTo("sex")==0)
		    	 {
		    		 index = desiredStates[parentIndices.get(nList.getNode(j).getName())];   // get the desired state for the node e.g. race = Hispanic
		    	 }
		    	 else
		    	 {
		    		 index = nn.state("True").getIndex();
		    	 }
		    	 pStates[parentIndices.get(nList.getNode(j).getName())] = index;
		      }
		      cptRow = nodeForOrgValue.getCPTable(pStates,null);
    		
    		
    		
    	} catch (ArrayIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NeticaException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return cptRow;
    }
    
    public Float calculateTrueProbScore(NodeList numeratorList, NodeList denominatorList, int[] pStates, Node nodeForRNOR)
    {
    	Float retVal = 0.0f;
    	float[] cptRow = {0.0f, 0.0f};
    	Float numer = 0.0f, denom = 0.0f;
    	
		cptRow = getCPTValueforNodeStates(numeratorList, nodeForRNOR, pStates);
		if (cptRow[0] == 0.5)
		{
			numer = linkProbsTrue.get(numeratorList.toString());
		}
		else
		{
			numer = Float.valueOf(cptRow[0]);
		//	numer = 1 - (1 - numer) / (1 - linkProbsTrue.get("global_leak"));
		}
    	
		
		cptRow = getCPTValueforNodeStates(denominatorList, nodeForRNOR, pStates);
	    if (cptRow[0] == 0.5)
		{
			denom = linkProbsTrue.get(denominatorList.toString());
		}
		else
		{
			denom = Float.valueOf(cptRow[0]);
		//	denom = 1 - (1 - denom) / (1 - linkProbsTrue.get("global_leak"));
		}
    	
    	Float Numerator = 1 - numer;
    	Float Denominator = 1 - denom;
    	
    	retVal = Numerator / Denominator;
    	
    	return retVal;
    }
    
    
    public Float calculateProbScore(NodeList numeratorList, NodeList denominatorList, int[] pStates, Node nodeForRNOR)
    {
    	Float retVal = 0.0f;
    	Float Numerator = 1 - linkProbs.get(numeratorList.toString());
    	Float Denominator = 1 - linkProbs.get(denominatorList.toString());
    	
    	retVal = Numerator / Denominator;
    	
    	return retVal;
    }
    
}